﻿using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

using BizElements.Core;

namespace BizElements.Generator
{
    public partial class MetaSourceCtl : UserControl
    {
        public MetaSourceCtl()
        {
            InitializeComponent();
        }

        #region Load.

        private void MetaSourceCtl_Load(object sender, EventArgs e)
        {
            this.uiOracle.Connected += new EventHandler<MetaDataSourceEventArgs>(OnConnected);
            this.uiOracle.Disconnected += new EventHandler<MetaDataSourceEventArgs>(OnDisconnected);
            this.uiSqlServer.Connected += new EventHandler<MetaDataSourceEventArgs>(OnConnected);
            this.uiSqlServer.Disconnected += new EventHandler<MetaDataSourceEventArgs>(OnDisconnected);
            this.uiSqlCe.Connected += new EventHandler<MetaDataSourceEventArgs>(OnConnected);            
            this.uiSqlCe.Disconnected += new EventHandler<MetaDataSourceEventArgs>(OnDisconnected);
            this.uiPostgreSql.Connected += new EventHandler<MetaDataSourceEventArgs>(OnConnected);
            this.uiPostgreSql.Disconnected += new EventHandler<MetaDataSourceEventArgs>(OnDisconnected);
            this.uiMySql.Connected += new EventHandler<MetaDataSourceEventArgs>(OnConnected);
            this.uiMySql.Disconnected += new EventHandler<MetaDataSourceEventArgs>(OnDisconnected);
            this.uiFirebird.Connected += new EventHandler<MetaDataSourceEventArgs>(OnConnected);
            this.uiFirebird.Disconnected += new EventHandler<MetaDataSourceEventArgs>(OnDisconnected);
            this.uiSQLite.Connected += new EventHandler<MetaDataSourceEventArgs>(OnConnected);
            this.uiSQLite.Disconnected += new EventHandler<MetaDataSourceEventArgs>(OnDisconnected);
            this.uiDB2.Connected += new EventHandler<MetaDataSourceEventArgs>(OnConnected);
            this.uiDB2.Disconnected += new EventHandler<MetaDataSourceEventArgs>(OnDisconnected);

            this.uiSupportedSources.DataSource = GetSupportedSource();
            this.uiSupportedSources.SelectedIndex = -1;
            this.uiSupportedSources.SelectedIndex = 0;
        }

        private static List<Pair<string, DbmsType>> GetSupportedSource()
        {
            List<Pair<string, DbmsType>> supportedMetaSources = new List<Pair<string, DbmsType>>()
            {
                new Pair<string, DbmsType>(Messages.SqlServer_2008, DbmsType.SqlServer_2008),
                new Pair<string, DbmsType>(Messages.SqlServer_2005, DbmsType.SqlServer_2005),
                new Pair<string, DbmsType>(Messages.SqlServer_2000, DbmsType.SqlServer_2000),
			    new Pair<string, DbmsType>(Messages.SqlServer_7, DbmsType.SqlServer_7),    			
                new Pair<string, DbmsType>(Messages.SqlServerCe_4, DbmsType.SqlServerCe_4),
                new Pair<string, DbmsType>(Messages.MySql_5, DbmsType.MySql_5),
                new Pair<string, DbmsType>(Messages.Oracle_11g, DbmsType.Oracle_11g),
			    new Pair<string, DbmsType>(Messages.Oracle_10g, DbmsType.Oracle_10g),
			    new Pair<string, DbmsType>(Messages.Oracle_9i, DbmsType.Oracle_9i),                
                new Pair<string, DbmsType>(Messages.PostgreSql_9, DbmsType.PostgreSql_9),
                new Pair<string, DbmsType>(Messages.Firebird_2, DbmsType.Firebird_2),
                new Pair<string, DbmsType>(Messages.SQLite_3, DbmsType.SQLite_3),
                new Pair<string, DbmsType>(Messages.DB2_9, DbmsType.DB2_9)
            };

            return supportedMetaSources;
        }

        #endregion

        #region Public properties and events.

        [Browsable(false)]
        public IMetadataSource MetaDataSource { get; private set; }
        public event EventHandler Connected;
        public event EventHandler Disconnected;

        private void OnConnected(object sender, MetaDataSourceEventArgs e)
        {
            this.MetaDataSource = e.MetaDataSource;
            if (this.Connected != null)
                Connected(this, new EventArgs());
        }

        private void OnDisconnected(object sender, MetaDataSourceEventArgs e)
        {
            this.MetaDataSource = null;
            if (this.Disconnected != null)
                Disconnected(this, new EventArgs());
        }

        #endregion

        #region Select metadata source.

        private void uiSupportedSources_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (uiSupportedSources.SelectedIndex >= 0)
                DisplaySelectedMetaSourceControl();
        }

        private void DisplaySelectedMetaSourceControl()
        {            
            DbmsType dbms = (DbmsType)this.uiSupportedSources.SelectedValue;
            IMetaDataSourceUi newCtl = GetMetaSourceControl(dbms);
            if (newCtl == null)
                throw new ArgumentException(Messages.MetaSourceCtl_SelectedDbmsIsNotSupported);

            IMetaDataSourceUi currControl = GetCurrentMetaSourceControl();
            if (currControl != null)
            {
                currControl.Control.Visible = false;
                if (currControl.MetaDataSource != null)
                    currControl.MetaDataSource.CloseConnection();
            }

            newCtl.Control.Location = new Point(6, 34);
            newCtl.Control.Visible = true;
            newCtl.Dbms = dbms;
        }

        private IMetaDataSourceUi GetCurrentMetaSourceControl()
        {
            if (this.uiSqlServer.Visible)
                return this.uiSqlServer;
            else if (this.uiOracle.Visible)
                return this.uiOracle;
            else if (this.uiSqlCe.Visible)
                return this.uiSqlCe;
            else if (this.uiPostgreSql.Visible)
                return this.uiPostgreSql;
            else if (this.uiMySql.Visible)
                return this.uiMySql;
            else if (this.uiFirebird.Visible)
                return this.uiFirebird;
            else if (this.uiSQLite.Visible)
                return this.uiSQLite;
            else if (this.uiDB2.Visible)
                return this.uiDB2;
            else
                return null;
        }

        private IMetaDataSourceUi GetMetaSourceControl(DbmsType dbms)
        {
            if (DbGeneratorComponentFactory.IsOracle(dbms))
                return this.uiOracle;
            else if (DbGeneratorComponentFactory.IsSqlServer(dbms))
                return this.uiSqlServer;
            else if (DbGeneratorComponentFactory.IsSqlCe(dbms))
                return this.uiSqlCe;
            else if (DbGeneratorComponentFactory.IsPostgreSql(dbms))
                return this.uiPostgreSql;
            else if (DbGeneratorComponentFactory.IsMySql(dbms))
                return this.uiMySql;
            else if (DbGeneratorComponentFactory.IsFirebird(dbms))
                return this.uiFirebird;
            else if (DbGeneratorComponentFactory.IsSQLite(dbms))
                return this.uiSQLite;
            else if (DbGeneratorComponentFactory.IsDB2(dbms))
                return this.uiDB2;
            else
                return null;
        }

        #endregion

        #region Settings.

        public void ReadSettings(BizElementsSettings projectSettings)
        {
            try 
            { 
                if (!string.IsNullOrEmpty(projectSettings["MetaSource_SelectedMetaDataSource"]))
                    this.uiSupportedSources.SelectedValue = (DbmsType)Enum.Parse(typeof(DbmsType), projectSettings["MetaSource_SelectedMetaDataSource"]); 
            }
            catch 
            { 
                this.uiSupportedSources.SelectedIndex = 0; 
            }

            DisplaySelectedMetaSourceControl();
            this.uiOracle.ReadSettings(projectSettings);
            this.uiSqlServer.ReadSettings(projectSettings);
            this.uiSqlCe.ReadSettings(projectSettings);
            this.uiPostgreSql.ReadSettings(projectSettings);
            this.uiMySql.ReadSettings(projectSettings);
            this.uiFirebird.ReadSettings(projectSettings);
            this.uiSQLite.ReadSettings(projectSettings);
            this.uiDB2.ReadSettings(projectSettings);
        }

        public void WriteSettings(BizElementsSettings projectSettings)
        {
            projectSettings["MetaSource_SelectedMetaDataSource"] = this.uiSupportedSources.SelectedValue.ToString();
            DbmsType currDbms = (DbmsType)this.uiSupportedSources.SelectedValue;
            var currControl = GetMetaSourceControl(currDbms);
            currControl.WriteSettings(projectSettings);
        }

        #endregion
    }

    interface IMetaDataSourceUi
    {
        UserControl Control { get; }
        DbmsType Dbms { get; set; }
        IMetadataSource MetaDataSource { get; }
        event EventHandler<MetaDataSourceEventArgs> Connected;
        event EventHandler<MetaDataSourceEventArgs> Disconnected;
        void ReadSettings(BizElementsSettings settings);
        void WriteSettings(BizElementsSettings settings);
    }

    public sealed class MetaDataSourceEventArgs : EventArgs
    {
        public MetaDataSourceEventArgs(IMetadataSource metaDataSource)
        {
            this.MetaDataSource = metaDataSource;
        }

        public IMetadataSource MetaDataSource { get; private set; }
    }
}
